iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0
自我挑戰組

從前端角度看30天學Python系列 第 27

【Day 27】Python for Web

  • 分享至 

  • xImage
  •  
  • 創造路由
  • 創造模板
  • Jinja
    • layout.html
    • {{ data }}

這篇文章是閱讀Asabeneh的30 Days Of Python: Day 26 - Python for Web後的學習筆記與心得。

原文章中 Day 24 與 Day 25 分別是說明 NumPy 以及 pandas 這兩個函式庫的函式,因為應用的部分著墨不多,就像是在讀官方 API 文件的感覺,因此我選擇略過不寫,直接跳到原文的 Day 26,這章會使用 Flask 做一個簡易的後端。


首先,需要架設一個環境,原文中給的資料夾結構如下,裡面是後續建置會用到的檔案:

├── Procfile
├── app.py
├── env
│   ├── bin
├── requirements.txt
├── static
│   └── css
│       └── main.css
└── templates
    ├── about.html
    ├── home.html
    ├── layout.html
    ├── post.html
    └── result.html

然後需要啟動 Day 26 提到的虛擬環境,若尚未安裝可以在 CLI 輸入pip install virtualenv 執行安裝:

(這是 Windows 的創建及啟動語法)

python -m venv venv
venv\Scripts\activate
pip install Flask
pip freeze > requirements.txt
"venv/*" > .gitignore
  1. 這邊 virtualenv 產生了一個 venv 資料夾
  2. 啟動虛擬環境
  3. 安裝 Flask 套件
  4. pip freeze 的輸出寫進 requirements.txt
  5. 創一個 .gitignore 檔案並排除 venv/ 資料夾底下的檔案

創造路由

先在資料夾 (原文中放在 python_for_web ) 中,創建一個 app.py 的檔案,內容為:

# 
from flask import Flask
import os

app = Flask(__name__)

@app.route('/') # Home
def home ():
    return <h1>Home</h1>

@app.route('/about')
def about():
    return <h1>About</h1>

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(debug=True, host='0.0.0.0', port = port)

__name__ 是 Python 在創造模組 (module) 時會自動加入的屬性,當模組是主要被執行的對象時 __name__ = '__main__' 否則會等於被引入的模組名稱。
如果沒有寫 if 判斷式的話,若這個模組被其他模組引入,就會在編譯的過程中被執行,通常這不會是我們想要的。

執行 python app.py 後可以看到:

* Running on http://127.0.0.1:5000

此時便能透過瀏覽器去拜訪 http://127.0.0.1:5000,看到 <h1>Home</h1> 這個元素。

創造模板

當我們拜訪網站時,應該不單純是只要 <h1>...</h1> 這樣的字串;Flask 能夠回傳 html 檔案:

  1. 首先創一個資料夾叫 templates
  2. 在這個資料夾內新增兩個檔案 home.htmlabout.html

home.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Home</title>
  </head>

  <body>
    <h1>Welcome Home</h1>
  </body>
</html>

about.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>About</title>
  </head>

  <body>
    <h1>About Us</h1>
  </body>
</html>
  1. 然後從 flask 新引入render_template 函式,並在路由底下回傳 render_template(<filename>)
from flask import Flask, render_template

# 沒改動的地方省略

@app.route('/') # Home
def home ():
    return render_template('home.html')

@app.route('/about')
def about():
    return render_template('about.html')

這麼一來 Flask 就會去 templates 資料夾抓到 home.htmlabout.html 並在使用者拜訪對應的位址時回傳對應的HTML檔案。?

Jinja

Flask 借助這個模板引擎,讓我們建立 HTML 模板並結合其他 HTML 檔案使用,也可以將 app.py 中的資料嵌入到我們的 HTML 檔案。

layout.html

從上面的例子可以看到,home.htmlabout.html 只有 h1 標籤內的內容不同:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>About</title>
  </head>

  <body>
    <!-- 只有這裡不一樣 -->
  </body>
</html>

透過 Jinja2 的語法,我們能避免重複撰寫這些共通的內容;在 templates 資料夾中新增一個 layout.html 檔案,內容為:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
</head>
<body>
{% block contents %}{% endblock %}
</body>
</html>

然後在原本的 home.html 就能改成:

{% extends "layout.html" %}

{% block contents %}
<h1>Welcome Home</h1>
{% endblock %}

about.html 也是:

{% extends "layout.html" %}

{% block contents %}
<h1>About Us</h1>
{% endblock %}

{{ data }}

經過上面的改寫,可以注意到瀏覽器的頁籤 (tab) 還是顯示 "Title",這是因為 layout.html<title>Title</title> 這個標籤內的內容並沒有透過 Jinja 來依資料改變。

app.py 中,我們使用的 render_template(<template>) 可以接受第二個參數:

# @filename = app.py
@app.route('/') # Home
def home ():
    return render_template('home.html', title = 'Home')

@app.route('/about')
def about():
    return render_template('about.html', title = 'About Us')

然後在 layout.html 裡把 title 標籤的內容修改為:

<title>{{ title }}</title>

這個 {{ data }} 的語法叫做 Mustache syntax

這樣就能看到 tab 的名稱隨著我們去到不同的路由改變了。


上一篇
【Day 26】虛擬環境
下一篇
【Day 28】Python with MongoDB
系列文
從前端角度看30天學Python30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言